//data:配置项中的数据
function Observer(data) {
    //this : Observer的实例对象
    this.data = data;
    this.walk(data);
}

Observer.prototype = {
    walk: function(data) {
        //me : Observer的实例对象 //this劫持
        var me = this;
        //Object.keys(data): 返回data中所有可枚举属性的属性名组成的数组
        Object.keys(data).forEach(function(key) {
            //key:data中的一个个属性名
            //data[key]: key在data中对应的val
            me.convert(key, data[key]);
        });
    },
    //key, val : data中一个个键值对
    convert: function(key, val) {
        //this : Observer的实例对象
        this.defineReactive(this.data, key, val);
    },
    //data:配置项中数据
    //key, val: data中一个个键值对
    //defineReactive 被调用多少次 取决于data有多少个直接属性
    defineReactive: function(data, key, val) {
        //key: damu damuname damuage wife wifename wifeage son sonname sonage a b
        //dep : 每一个key都拥有一个dep闭包  dep有着一个唯一性的id
        var dep = new Dep();
        var childObj = observe(val);

        //当val不再是一个对象时 我们就会为当前这个val执行以下的代码
        //真正数据劫持的代码
        //key: damuname damuage wifename wifeage sonname sonage son wife damu a b
        //data: 永远是离key最近的那个对象
        //val是一个闭包  val对应的都是key在data中存的值
        Object.defineProperty(data, key, {
            enumerable: true, // 可枚举
            configurable: false, // 不能再define
            get: function() {
                if (Dep.target) {
                    //a.dep  b.dep msg.dep
                    dep.depend();
                }
                return val;
            },
            set: function(newVal) {
                if (newVal === val) {
                    return;
                }
                val = newVal;
                //如果新增的值是一个对象 这个对象也得做数据劫持
                childObj = observe(newVal);
                //notify:通知
                dep.notify();
            }
        });
    }
};

//value : 配置项中的数据
//vm    : MVVM的实例对象
function observe(value, vm) {
    //看门狗 咬流程
    if (!value || typeof value !== 'object') {
        return;
    }

    //确保value是object 并且还不是null
    return new Observer(value);
};


var uid = 0;

function Dep() {
    this.id = uid++;
    //存的是一个dep对应的所有watcher
    this.subs = [];
}

Dep.prototype = {
    addSub: function(sub) {
        this.subs.push(sub);
    },

    depend: function() {
        //this : a.dep  b.dep msg.dep
        //{{a.b.msg}}.watcher.addDep(this)
        Dep.target.addDep(this);
    },

    removeSub: function(sub) {
        var index = this.subs.indexOf(sub);
        if (index != -1) {
            this.subs.splice(index, 1);
        }
    },

    notify: function() {
        this.subs.forEach(function(sub) {
            sub.update();
        });
    }
};

Dep.target = null;